<?php
########## Proxy config ######
$proxyAddr = "";
$proxyPort = "";
$proxyUserName = "";
$proxyPassword = "";
##############################

header("Content-type: text/html; charset=utf-8");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Expires: 0");
header("Pragma: public");

error_reporting(E_ALL & ~E_NOTICE);

if (version_compare(phpversion(), '7.4.0') == -1)
{
	die('PHP 7.4.0 or higher is required!');
}

if (!function_exists('gzopen'))
{
	die('zlib module is not installed!');
}

ob_implicit_flush();
set_time_limit(1800);

define('TIMEOUT', 10);

if (isset($_REQUEST['lang']))
{
	$lang = $_REQUEST['lang'];

	if (!in_array($lang, ['ru','en','de']))
	{
		$lang = 'en';
	}
}
elseif (preg_match('#ru#i', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''))
{
	$lang = 'ru';
}
elseif (preg_match('#de#i', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''))
{
	$lang = 'de';
}
else
{
	$lang = 'en';
}

define("LANG", $lang);
define('UPDATE_FLAG', dirname(__FILE__).'/bitrixsetup.update');

$this_script_name = basename(__FILE__);

umask(0);
if (file_exists($file = $_SERVER['DOCUMENT_ROOT'].'/bitrix/php_interface/dbconn.php'))
{
	include($file);
}

$debug = file_exists(dirname(__FILE__).'/bitrixsetup.debug');

if (!defined("BX_DIR_PERMISSIONS"))
{
	define("BX_DIR_PERMISSIONS", 0755);
}

if (!defined("BX_FILE_PERMISSIONS"))
{
	define("BX_FILE_PERMISSIONS", 0644);
}

$strAction = $_REQUEST["action"] ?? '';
$edition = $_REQUEST['edition'] ?? 0;

if ($short = (getenv('BITRIX_ENV_TYPE') == 'crm'))
{
	$arEditions = array(
		'ru' => array(
			array(
				'NAME' => '1С-Битрикс24',
				'LIST' => array(
					'portal/bitrix24' => 'Корпоративный портал',
					'portal/bitrix24_enterprise' => 'Энтерпрайз',
					'portal/bitrix24_crm' => 'Битрикс24.CRM'

				)
			),
		),
		'en' => array(
			array(
				'NAME' => 'Bitrix24',
				'LIST' => array(
					'portal/en_bitrix24_crm' => "Bitrix24.CRM",
					'portal/en_bitrix24' => 'Business',
					'portal/en_bitrix24_enterprise' => 'Enterprise'
				),
			)
		),
		'de' => array(
			array(
				'NAME' => 'Bitrix24',
				'LIST' => array(
					'de/de_bitrix24_crm' => "Bitrix24.CRM",
					'de/de_bitrix24' => 'Business',
					'de/de_bitrix24_enterprise' => 'Enterprise'
				)
			)
		)
	);

	$edition = 0;
}
else
{
	$arEditions = array(
		'ru' => array(
			array(
				'NAME' => '1С-Битрикс: Управление сайтом',
				'LIST' => array(
					"business"=>"Бизнес",
					"small_business"=>"Малый бизнес",
					"standard"=>"Стандарт",
					"start"=>"Старт",
				),
			),
			array(
				'NAME' => '1С-Битрикс24',
				'LIST' => array(
					'portal/bitrix24_shop' => 'Интернет-магазин плюс CRM',
					'portal/bitrix24' => 'Корпоративный портал',
					'portal/bitrix24_enterprise' => 'Энтерпрайз',
				)
			),
			array(
				'NAME' => 'Отраслевые решения 1С-Битрикс',
				'LIST' => array(
					'edu/eduportal' => 'Внутренний портал учебного заведения',
				),
			),
		),
		'en' => array(
			array(
				'NAME' => 'Bitrix24',
				'LIST' => array(
					'portal/en_bitrix24' => 'Business',
					'portal/en_bitrix24_enterprise' => 'Enterprise'
				),
			)
		),
		'de' => array(
			array(
				'NAME' => 'Bitrix24',
				'LIST' => array(
					'de/de_bitrix24' => 'Business',
					'de/de_bitrix24_enterprise' => 'Enterprise'
				),
			)
		)
	);
}
$single = count($arEditions[LANG]) == 1;

if (LANG == "ru")
{
	$MESS = [
		"NO_PERMS" => "Нет прав на запись в файл ",
		"LOADER_LICENSE_KEY" => "Лицензионный ключ",
		"INTRANET" => "Корпоративный портал",
		"LOADER_TITLE" => "Загрузка продуктов \"1С-Битрикс\"",
		"UPDATE_SUCCESS" => "Обновлено успешно. <a href='?'>Открыть</a>.",
		"LOADER_NEW_STEPS" => "Загрузка продуктов \"1С-Битрикс\"",
		"LOADER_SUBTITLE1" => "Загрузка продукта",
		"LOADER_SUBTITLE2" => "1С-Битрикс",
		"LOADER_MENU_LIST" => "Выбор продукта",
		"LOADER_MENU_LOAD" => "Загрузка дистрибутива с сервера",
		"LOADER_MENU_UNPACK" => "Распаковка дистрибутива",
		"LOADER_TECHSUPPORT" => "",
		"LOADER_TITLE_LIST" => "Выбор дистрибутива",
		"LOADER_TITLE_LOAD" => "Загрузка дистрибутива на сайт",
		"LOADER_TITLE_UNPACK" => "Распаковка дистрибутива",
		"LOADER_TITLE_LOG" => "Отчет по загрузке",
		"LOADER_SAFE_MODE_ERR" => "<font color=\"#FF0000\"><b>Внимание!</b></font> PHP на вашем сайте работает в Safe Mode. Установка продукта в автоматическом режиме невозможна. Пожалуйста, обратитесь в службу технической поддержки для получения дополнительной информации.",
		"LOADER_NO_PERMS_ERR" => "<font color=\"#FF0000\"><b>Внимание!</b></font> PHP не имеет прав на запись в корневую папку #DIR# вашего сайта. Загрузка продукта может оказаться невозможной. Пожалуйста, установите необходимые права на корневую папку вашего сайта или обратитесь к администраторам вашего хостинга.",
		"LOADER_EXISTS_ERR" => "",
		"LOADER_IS_DISTR" => "На сайте найдены загруженые дистрибутивы. Нажмите на название любого из дистрибутивов для его распаковки:",
		"LOADER_OVERWRITE" => "<b>Внимание!</b> Существующие на сайте файлы могут быть перезаписаны файлами из дистрибутива.",
		"LOADER_IS_DISTR_PART" => "На сайте найдены недогруженные дистрибутивы. Нажмите на название любого из недогруженных дистрибутивов для полной загрузки:",
		"LOADER_NEW_LOAD_TITLE" => "Загрузка дистрибутива с сайта <a href=\"https://www.1c-bitrix.ru\" target=\"_blank\">https://www.1c-bitrix.ru</a>",
		"LOADER_NEW_ED" => "Выбор дистрибутива",
		"LOADER_NEW_VERSION" => "Доступна новая версия скрипта установки, но загрузить её не удалось",
		"LOADER_NEW_AUTO" => "Автоматически запустить распаковку после загрузки",
		"LOADER_NEW_STEPS" => "Загружать по шагам с шагом",
		"LOADER_NEW_STEPS0" => "неограниченно долгим",
		"LOADER_NEW_STEPS30" => "не более 30 секунд",
		"LOADER_NEW_STEPS60" => "не более 60 секунд",
		"LOADER_NEW_STEPS120" => "не более 120 секунд",
		"LOADER_NEW_STEPS180" => "не более 180 секунд",
		"LOADER_NEW_STEPS240" => "не более 240 секунд",
		"LOADER_NEW_LOAD" => "Загрузить",
		"LOADER_DESCR" => "Этот скрипт предназначен для загрузки дистрибутивов \"1С-Битрикс\" с сайта <a href=\"https://www.1c-bitrix.ru/download/index.php\" target=\"_blank\">www.1c-bitrix.ru</a> непосредственно на ваш сайт, а так же для распаковки дистрибутива на вашем сайте.<br><br> Загрузите этот скрипт в корневую папку вашего сайта и откройте его в браузере (введите в адресной строке браузера <nobr>http://&lt,ваш сайт&gt,/".$this_script_name."</nobr>).",
		"LOADER_BACK_2LIST" => "Вернуться в список дистрибутивов",
		"LOADER_BACK" => "Назад",
		"LOADER_LOG_ERRORS" => "Произошли следующие ошибки:",
		"LOADER_NO_LOG" => "Log-файл не найден",
		"LOADER_BOTTOM_NOTE1" => "<b><font color=\"#FF0000\">Внимание!</font></b> По окончании установки продукта <b>обязательно</b> удалите скрипт <nobr>/".$this_script_name."</nobr> с вашего сайта. Доступ постороннего человека к этому скрипту может повлечь за собой нарушение работы вашего сайта.",
		"LOADER_KB" => "кб",
		"LOADER_LOAD_QUERY_SERVER" => "Запрашиваю сервер...",
		"LOADER_LOAD_QUERY_DISTR" => "Запрашиваю дистрибутив #DISTR#",
		"LOADER_LOAD_CONN2HOST" => "Открываю соединение к #HOST#...",
		"LOADER_LOAD_NO_CONN2HOST" => "Не могу соединиться с #HOST#:",
		"LOADER_LOAD_QUERY_FILE" => "Запрашиваю файл...",
		"LOADER_LOAD_WAIT" => "Ожидаю ответ...",
		"LOADER_LOAD_SERVER_ANSWER" => "Ошибка загрузки. Ответа сервера:<br><br> #ANS#",
		"LOADER_LOAD_SERVER_ANSWER1" => "Ответ сервера: 403 Доступ запрещён.<br>Проверьте правильность ввода ключа.",
		"LOADER_LOAD_NEED_RELOAD" => "Докачка дистрибутива невозможна. Начинаю качать заново.",
		"LOADER_LOAD_NO_WRITE2FILE" => "Не могу открыть файл #FILE# на запись",
		"LOADER_LOAD_LOAD_DISTR" => "Загружаю дистрибутив #DISTR#",
		"LOADER_LOAD_ERR_SIZE" => "Ошибка размера файла",
		"LOADER_LOAD_ERR_RENAME" => "Не могу переименовать файл #FILE1# в файл #FILE2#",
		"LOADER_LOAD_CANT_OPEN_WRITE" => "Не могу открыть файл #FILE# на запись",
		"LOADER_LOAD_CANT_OPEN_READ" => "Не могу открыть файл #FILE# на чтение",
		"LOADER_LOAD_LOADING" => "Загружаю файл... дождитесь окончания загрузки...",
		"LOADER_LOAD_FILE_SAVED" => "Файл сохранен: #FILE# [#SIZE# байт]",
		"LOADER_UNPACK_ACTION" => "Распаковываю дистрибутив... дождитесь окончания распаковки...",
		"LOADER_UNPACK_UNKNOWN" => "Неизвестная ошибка. Повторите процесс еще раз или обратитесь в службу технической поддержки",
		"LOADER_UNPACK_DELETE" => "Ошибка удаления временных файлов. Удалите файлы вручную.",
		"LOADER_UNPACK_SUCCESS" => "Дистрибутив успешно распакован",
		"LOADER_UNPACK_ERRORS" => "Дистрибутив распакован с ошибками",
		"LOADER_KEY_DEMO" => "Демонстрационная версия",
		"LOADER_KEY_COMM" => "Коммерческая версия",
		"LOADER_KEY_TITLE" => "Введите лицензионный ключ",
		"LOADER_NOT_EMPTY" => "В текущей папке уже есть установленная версия продукта, установка новой версии возможна только в чистую корневую папку веб-сервера.",
	];
}
elseif (LANG == "de")
{
	$MESS =	[
		"NO_PERMS" => "Nicht genunugend Rechte um die Datei zu beschreiben",
		"LOADER_LICENSE_KEY" => "Lizenzschlussel",
		"INTRANET" => "Intranet Portal ",
		"LOADER_TITLE" => "Download der \"Bitrix24\" Software",
		"UPDATE_SUCCESS" => "Aktualisierung erfolgreich durchgefuhrt. <a href='?'>Offnen?</a>.",
		"LOADER_NEW_STEPS" => "Download der \"Bitrix24\" Software",
		"LOADER_SUBTITLE1" => "Softwaredownload",
		"LOADER_SUBTITLE2" => "Bitrix24",
		"LOADER_MENU_LIST" => "Auswahl des Installationspacks",
		"LOADER_MENU_LOAD" => "Download des Installationspacks von dem Server",
		"LOADER_MENU_UNPACK" => "Auspacken des Installationspacks",
		"LOADER_TECHSUPPORT" => "",
		"LOADER_TITLE_LIST" => "Auswahl des Installationspacks",
		"LOADER_TITLE_LOAD" => "Upload des Installationspacks auf die Website",
		"LOADER_TITLE_UNPACK" => "Auspacken des Installationspacks",
		"LOADER_TITLE_LOG" => "Uploadbericht",
		"LOADER_SAFE_MODE_ERR" => "<font color=\"#FF0000\"><b>Achtung!</b></font> PHP auf Ihrer Website arbeitet im Safe Mode. Die automatische Installation der Software ist nicht moglich. Bitte wenden Sie sich fur weitere Informationen an den technischen Support.",
		"LOADER_NO_PERMS_ERR" => "<font
color=\"#FF0000\"><b>Achtung!</b></font> PHP hat nicht genugend Rechte um das Hautverzeichnis #DIR# Ihrer Website zu uberschreiben. Es konnen Fehler bei der Installation auftreten. Bitte stellen Sie alle erforderlichen Rechte ein, oder wenden Sie sich an Ihren Hosting-Anbieter.",
		"LOADER_EXISTS_ERR" => "",
		"LOADER_IS_DISTR" => "Hochgeladene Installationspacks wurden gefunden. Klicken Sie auf den Namen des erforderlichen Installationspacks um mit dem Auspacken zu beginnen:",
		"LOADER_OVERWRITE" => "<b>Achtung!</b> Die existierenden Dateien konnen durch die Dateien aus dem Installationspack uberschrieben werden.",
		"LOADER_IS_DISTR_PART" => "Auf der Website wurden nicht vollstandig geladenen Installationspacks hochgeladen. Klicken Sie auf den Namen des erforderlichen Installationspacks um mit Upload fortzufuhren:",
		"LOADER_NEW_LOAD_TITLE" => "Download des Installationspacks von der Site <a href=\"https://www.bitrix.de\" target=\"_blank\">https://www.bitrix.de</a>",
		"LOADER_NEW_ED" => "Auswahl des Installationspacks",
		"LOADER_NEW_VERSION" => "Neue Version des Installationsskripts ins verfugbar!",
		"LOADER_NEW_AUTO" => "Auspacken automatisch nach dem Upload starten",
		"LOADER_NEW_STEPS" => "Hochladen in folgenden Schritten",
		"LOADER_NEW_STEPS0" => "uneingeschrankt ",
		"LOADER_NEW_STEPS30" => "max. 30 Sekunden",
		"LOADER_NEW_STEPS60" => " max. 60 Sekunden",
		"LOADER_NEW_STEPS120" => "max. 120 Sekunden",
		"LOADER_NEW_STEPS180" => "max. 180 Sekunden",
		"LOADER_NEW_STEPS240" => "max. 240 Sekunden",
		"LOADER_NEW_LOAD" => "Hochladen",
		"LOADER_DESCR" => "Dieses Skript ist dient dem Download der \"Bitrix24\"-Installationspacks von der Website <a
href=\"https://www.bitrix24.de/prices/self-hosted.php\" target=\"_blank\">www.bitrix24.de</a> direkt auf Ihre Website, sowie dem Auspacken des Installationspacks auf Ihrer Website.<br><br> 
Laden Sie dieses Skript in das Hauptverzeichnis, und offnen Sie es in Ihrem Internet-Browser. Geben Sie dafur in der Adresszeile <nobr>https://&amp;lt;IhreWebsite&amp;gt;/".$this_script_name."</nobr>).",
		"LOADER_BACK_2LIST" => "Zur der Installationspack-Liste zuruckkehren",
		"LOADER_BACK" => "Zurück",
		"LOADER_LOG_ERRORS" => "Folgende Fehler sind aufgetreten:",
		"LOADER_NO_LOG" => "Log-Datei nicht gefunden",
		"LOADER_BOTTOM_NOTE1" => "<b><font color=\"#FF0000\">Achtung!</font></b> Nach der Installation des Produkts loschen Sie <b>unbedingt</b> das Skript<nobr>/".$this_script_name."</nobr> von Ihrer Website. Der Fremdzugriff zu diesem Skript kann fehlerhafte Funktion Ihrer Website mit sich fuhren.",
		"LOADER_KB" => "kb",
		"LOADER_LOAD_QUERY_SERVER" => "Anfrage an den Server...",
		"LOADER_LOAD_QUERY_DISTR" => "Anfrage fur das Installationspack #DISTR#",
		"LOADER_LOAD_CONN2HOST" => "Aufbau der Verbindung mit #HOST#...",
		"LOADER_LOAD_NO_CONN2HOST" => "Keine Verbindung mit #HOST#:",
		"LOADER_LOAD_QUERY_FILE" => "Anfrage fur die Datei...",
		"LOADER_LOAD_WAIT" => "Abwarten der Ruckmeldung...",
		"LOADER_LOAD_SERVER_ANSWER" => "Upload-Fehler. Serverruckmeldung:<br><br> #ANS#",
		"LOADER_LOAD_SERVER_ANSWER1" => " Serverruckmeldung: 403 Zugriff verweigert.<br>Uberprufen Sie die Richtigkeit des Codes.",
		"LOADER_LOAD_NEED_RELOAD" => "Fortfuhrung des Downloadvorgangs nicht moglich. Der Downloadvorgang wird erneut ausgefuhrt.",
		"LOADER_LOAD_NO_WRITE2FILE" => "Die #FILE# kann nicht bearbeitet werden",
		"LOADER_LOAD_LOAD_DISTR" => "Installationspack #DISTR# wird hochgeladen",
		"LOADER_LOAD_ERR_SIZE" => "Fehler bei der Dateigro?e",
		"LOADER_LOAD_ERR_RENAME" => "Die Datei #FILE1# kann nicht in #FILE2# umbenannt warden",
		"LOADER_LOAD_CANT_OPEN_WRITE" => "Die Datei #FILE# kann nicht bearbeitet werden",
		"LOADER_LOAD_CANT_OPEN_READ" => "Die Datei #FILE# kann nicht gelesen werden",
		"LOADER_LOAD_LOADING" => "Upload-Vorgang lauft... Bitte warten Sie bis der Vorgang beendet wird.",
		"LOADER_LOAD_FILE_SAVED" => "Datei gespeichert: #FILE# [#SIZE# Byte]",
		"LOADER_UNPACK_ACTION" => " Das Installationspack wird ausgepackt... Bitte warten Sie bis der Vorgang beendet wird.",
		"LOADER_UNPACK_UNKNOWN" => "Unbekannter Fehler. Fuhren Sie den Vorgang nochmal aus, oder wenden Sie sich an den technischen Support",
		"LOADER_UNPACK_DELETE" => "Fehler beim Loschen der temporaren Dateien. Loschen Sie bitte die Dateien manuell.",
		"LOADER_UNPACK_SUCCESS" => "Das Installationspack wurde erfolgreich ausgepackt",
		"LOADER_UNPACK_ERRORS" => " Das Installationspack wurde mit Fehlern ausgepackt ",
		"LOADER_KEY_DEMO" => "Testversion",
		"LOADER_KEY_COMM" => "Vollversion",
		"LOADER_KEY_TITLE" => "Lizenzcode eingeben",
		"LOADER_NOT_EMPTY" => "Es existiert bereits eine Produktversion im aktuellen Ordner. Eine neue Version kann nur in einem leeren Root-Verzeichnis des Webservers installiert werden.",
	];
}
else
{
	$MESS = [
		"NO_PERMS" => "No permissions to write the file ",
		"LOADER_LICENSE_KEY" => "Your license key",
		"INTRANET" => "Bitrix Intranet Portal",
		"LOADER_TITLE" => "Loading Product \"Bitrix24\"",
		"UPDATE_SUCCESS" => "Successful update. <a href='?'>Open</a>.",
		"LOADER_SUBTITLE1" => "Loading",
		"LOADER_SUBTITLE2" => "Bitrix24",
		"LOADER_MENU_LIST" => "Choose a package",
		"LOADER_MENU_LOAD" => "Download installation package from server",
		"LOADER_MENU_UNPACK" => "Unpacking the Installation Package",
		"LOADER_TECHSUPPORT" => "",
		"LOADER_TITLE_LIST" => "Select installation package",
		"LOADER_TITLE_LOAD" => "Uploading installation package to the site",
		"LOADER_TITLE_UNPACK" => "Unpacking the Installation Package",
		"LOADER_TITLE_LOG" => "Upload report",
		"LOADER_SAFE_MODE_ERR" => "<font color=\"#FF0000\"><b>Attention!</b></font> Your PHP functions in Safe Mode. The Setup cannot proceed in automatic mode. Please consult the technical support service for additional instructions.",
		"LOADER_NO_PERMS_ERR" => "<font color=\"#FF0000\"><b>Attention!</b></font> PHP has not enough permissions to write to the root directory #DIR# of your site. Loading is likely to fail. Please set the required access permissions to the root directory of your site or consult administrators of your hosting service.",
		"LOADER_EXISTS_ERR" => "",
		"LOADER_IS_DISTR" => "Uploaded installation packages were found on the site. Click the name of any package to start installation:",
		"LOADER_OVERWRITE" => "<b>Attention!</b> Files currently present on your site will possibly be overwritten with files from the package.",
		"LOADER_IS_DISTR_PART" => "Incompletely uploaded installation packages were found on the site. Click the name of any package to finish loading:",
		"LOADER_NEW_LOAD_TITLE" => "Download new installation package from <a href=\"https://www.bitrix24.com\" target=\"_blank\">https://www.bitrix24.com</a>",
		"LOADER_NEW_VERSION" => "New version of bitrixsetup script is available!",
		"LOADER_NEW_ED" => "Choose a package",
		"LOADER_NEW_AUTO" => "automatically start unpacking after loading",
		"LOADER_NEW_STEPS" => "load gradually with interval:",
		"LOADER_NEW_STEPS0" => "unlimited",
		"LOADER_NEW_STEPS30" => "less than 30 seconds",
		"LOADER_NEW_STEPS60" => "less than 60 seconds",
		"LOADER_NEW_STEPS120" => "less than 120 seconds",
		"LOADER_NEW_STEPS180" => "less than 180 seconds",
		"LOADER_NEW_STEPS240" => "less than 240 seconds",
		"LOADER_NEW_LOAD" => "Download",
		"LOADER_DESCR" => "",
		"LOADER_BACK_2LIST" => "Back to packages list",
		"LOADER_BACK" => "Back",
		"LOADER_LOG_ERRORS" => "The following errors occured:",
		"LOADER_NO_LOG" => "Log file not found",
		"LOADER_BOTTOM_NOTE1" => "<b><font color=\"#FF0000\">Attention!</font></b> After you have finished installing, <b>please be sure</b> to delete the script <nobr>/".$this_script_name."</nobr> from your site. Otherwise, unauthorized persons may access this script and damage your site.",
		"LOADER_KB" => "kb",
		"LOADER_LOAD_QUERY_SERVER" => "Connecting server...",
		"LOADER_LOAD_QUERY_DISTR" => "Requesting package #DISTR#",
		"LOADER_LOAD_CONN2HOST" => "Establishing connection to #HOST#...",
		"LOADER_LOAD_NO_CONN2HOST" => "Cannot connect to #HOST#:",
		"LOADER_LOAD_QUERY_FILE" => "Requesting file...",
		"LOADER_LOAD_WAIT" => "Waiting for response...",
		"LOADER_LOAD_SERVER_ANSWER" => "Error while downloading. Server reply was: #ANS#",
		"LOADER_LOAD_SERVER_ANSWER1" => "Server reply: 403 Forbidden.<br>Please check your licence key.",
		"LOADER_LOAD_NEED_RELOAD" => "Cannot resume download. Starting new download.",
		"LOADER_LOAD_NO_WRITE2FILE" => "Cannot open file #FILE# for writing",
		"LOADER_LOAD_LOAD_DISTR" => "Downloading package #DISTR#",
		"LOADER_LOAD_ERR_SIZE" => "File size error",
		"LOADER_LOAD_ERR_RENAME" => "Cannot rename file #FILE1# to #FILE2#",
		"LOADER_LOAD_CANT_OPEN_WRITE" => "Cannot open file #FILE# for writing",
		"LOADER_LOAD_CANT_OPEN_READ" => "Cannot open file #FILE# for reading",
		"LOADER_LOAD_LOADING" => "Download in progress. Please wait...",
		"LOADER_LOAD_FILE_SAVED" => "File saved: #FILE# [#SIZE# bytes]",
		"LOADER_UNPACK_ACTION" => "Unpacking the package. Please wait...",
		"LOADER_UNPACK_UNKNOWN" => "Unknown error occured. Please try again or consult the technical support service",
		"LOADER_UNPACK_DELETE" => "Errors occured while deleting temporary files",
		"LOADER_UNPACK_SUCCESS" => "The installation package successfully unpacked",
		"LOADER_UNPACK_ERRORS" => "Errors occured while unpacking the installation package",
		"LOADER_KEY_DEMO" => "Demo version",
		"LOADER_KEY_COMM" => "Commercial version",
		"LOADER_KEY_TITLE" => "Specify license key",
		"LOADER_NOT_EMPTY" => "An instance of the system already exists in the current folder. New version can only be installed to an empty folder in the web server root.",
	];
}

function LoaderGetMessage($name)
{
	global $MESS;
	return $MESS[$name];
}

if (LANG == 'ru')
{
	$bx_host = 'www.1c-bitrix.ru';
}
elseif (LANG == 'de')
{
	$bx_host = 'www.bitrix.de';
}
else
{
	$bx_host = 'www.bitrixsoft.com';
}

$bx_url = '/download/files/scripts/'.$this_script_name;
$strError = '';

if (!$strAction)
{
	if (!$debug && file_exists($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main'))
	{
		die(ShowError(LoaderGetMessage('LOADER_NOT_EMPTY')));
	}
	$strAction = "LIST";

	// Check for updates
	if ((!file_exists(UPDATE_FLAG) || time() - filemtime(UPDATE_FLAG) > 3600) && !$debug && !$proxyAddr)
	{
		file_put_contents(UPDATE_FLAG, time());
		$res = @fsockopen('ssl://'.$bx_host, 443, $errno, $errstr, 3);

		if ($res)
		{
			$strRequest = "HEAD ".$bx_url." HTTP/1.1\r\n";
			$strRequest.= "Host: ".$bx_host."\r\n";
			$strRequest.= "\r\n";

			fputs($res, $strRequest);

			while ($line = fgets($res, 4096))
			{
				if (@preg_match("/Content-Length: *([0-9]+)/i", $line, $regs))
				{
					if (filesize(__FILE__) != trim($regs[1]))
					{
						$tmp_name = $this_script_name.'.tmp';
						if (LoadFile('https://'.$bx_host.$bx_url, $tmp_name, 0))
						{
							if (rename($_SERVER['DOCUMENT_ROOT'].'/'.$tmp_name,__FILE__))
							{
								bx_accelerator_reset();
								echo '<script>document.location="?lang='.LANG.'";</script>'.LoaderGetMessage('UPDATE_SUCCESS');
								die();
							}
							else
							{
								$strError = str_replace("#FILE#", $this_script_name, LoaderGetMessage("LOADER_LOAD_CANT_OPEN_WRITE"));
							}
						}
						else
						{
							$strError = LoaderGetMessage('LOADER_NEW_VERSION');
						}
					}
					break;
				}
			}
			fclose($res);
		}
	}
}

if ($strAction == "UNPACK" && empty($_REQUEST["filename"]))
{
	$strAction = "LIST";
}

$ar = [];
$form = '';
$script = '';

if ($strAction == "LIST")
{
	$txt = '';
	if ($strError)
	{
		$txt = ShowError($strError);
	}

	if (ini_get("safe_mode") == "1")
	{
		$txt .= LoaderGetMessage("LOADER_SAFE_MODE_ERR") . '<br>';
	}

	if (!is_writable($_SERVER["DOCUMENT_ROOT"]))
	{
		$txt .= str_replace("#DIR#", $_SERVER["DOCUMENT_ROOT"], LoaderGetMessage("LOADER_NO_PERMS_ERR")) . '<br>';
	}

	if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix") && is_dir($_SERVER["DOCUMENT_ROOT"]."/bitrix"))
	{
		$txt .= LoaderGetMessage("LOADER_EXISTS_ERR") . '<br>';
	}

	$arLocalDistribs = [];
	$arLocalDistribs_tmp = [];

	$handle = opendir($_SERVER["DOCUMENT_ROOT"]);
	if (isset($_REQUEST['test']) && $_REQUEST['test'] && $handle)
	{
		while (false !== ($ffile = readdir($handle)))
		{
			if (!is_file($_SERVER["DOCUMENT_ROOT"]."/".$ffile))
			{
				continue;
			}

			if (strtolower(substr($ffile, -7)) == ".tar.gz")
			{
				$arLocalDistribs[] = $ffile;
			}
			elseif (strtolower(substr($ffile, -11)) == ".tar.gz.tmp")
			{
				$arLocalDistribs_tmp[] = $ffile;
			}
			elseif (strtolower(substr($ffile, -11)) == ".tar.gz.log")
			{
				$arLocalDistribs_tmp[] = $ffile;
			}
		}
		closedir($handle);
	}

	if (!empty($arLocalDistribs))
	{
		$txt .= LoaderGetMessage("LOADER_IS_DISTR").'<br>';
		for ($i = 0, $n = count($arLocalDistribs); $i < $n; $i++)
		{
			$txt .= '<a href="'.$this_script_name.'?action=UNPACK&filename='.urlencode($arLocalDistribs[$i]).'&by_step=Y">'.$arLocalDistribs[$i].'</a><br><br>';
		}
		$txt .= LoaderGetMessage("LOADER_OVERWRITE") . '<br><br>';
	}

	if (!empty($arLocalDistribs_tmp) && isset($_REQUEST['action']) && $_REQUEST['action'] == 'LIST')
	{
		foreach ($arLocalDistribs_tmp as $distr)
		{
			@unlink($_SERVER['DOCUMENT_ROOT'].'/'.$distr);
		}
	}

	$txt .= '<script>
		function show_select(k)
		{
			document.getElementById("download_button").disabled = false;
	';

	foreach ($arEditions[LANG] as $k => $ED)
	{
		$txt .= 'if (ob = document.getElementById("select_'.$k.'"))
				ob.disabled = "disabled";
			';
	}
	$txt .= '
			if (ob = document.getElementById("select_" + k))
				ob.disabled = "";
		}
		</script>
	';

	$form = '
	<form method="post" action="'.$this_script_name.'?action=LOAD" onsubmit="document.getElementById(\'download_button\').disabled=true">
	<input type=hidden name=lang value="'.LANG.'">
	';

	$txt .= '<table cellspacing=0 cellpadding=2 border=0>';
	$txt .= '<tr><td colspan=2>'.( $single ? '' : LoaderGetMessage("LOADER_NEW_ED").':').'</td></tr>';

	foreach($arEditions[LANG] as $k => $ED)
	{
		if ($single)
		{
			$txt.=' 
			<tr><td style="padding-left:10px;font-weight:bold"><input type=hidden name=edition value=0>'.$ED['NAME'].'</td>';
		}
		else
		{
			$txt.=' 
			<tr><td style="padding-left:10px;width:46%;"><input name=edition type=radio value="'.$k.'" id="radio_'.$k.'" onclick="show_select('.$k.')"> <label for="radio_'.$k.'">'.$ED['NAME'].'</label></td>';
		}

		$txt .= '<td>';
		if (is_array($ED['LIST']))
		{
			$txt .= '
				<select name="url" '.($single ? '' : 'disabled').' id="select_'.$k.'">';
			foreach ($ED['LIST'] as $key => $value)
			{
				$txt .= '<option value="'.$key.'">'.$value.'</option>';
			}
			$txt .= '
				</select>';
		}
		$txt .= '</td>';
	}

	$txt.='
		<tr>
			<td colspan=2 height=15></td>
		</tr>
		<tr>
			<td colspan=2 style="padding-left:10px; width: 46%"><input type="radio" name="licence_type" value="demo" checked id="licence_type_1" onclick="document.getElementById(\'license_key\').disabled=\'disabled\'"><label for="licence_type_1">'.LoaderGetMessage("LOADER_KEY_DEMO").'</label></td>
		</tr>
		<tr>
			<td colspan=2 style="padding-left:10px"><input type="radio" name="licence_type" value="src" id="licence_type_2" onclick="document.getElementById(\'license_key\').disabled=\'\'"><label for="licence_type_2">'.LoaderGetMessage("LOADER_KEY_COMM").'</label></td>
		</tr>
		<tr>
			<td style="padding-left:30px;">'.LoaderGetMessage("LOADER_LICENSE_KEY").': </td>
			<td><input type="text" disabled value="" id="license_key" name="LICENSE_KEY" size="40" title="'.LoaderGetMessage("LOADER_KEY_TITLE").'"></td>
		</tr>				
				
	</table>';

	$ar = array(
		'FORM' => $form,
		'TITLE' => LoaderGetMessage("LOADER_TITLE"),
		'HEAD' => LoaderGetMessage("LOADER_MENU_LIST"),
		'TEXT' => $txt,
		'TEXT_ALIGN' => 'top',
		'BOTTOM' => (file_exists($_SERVER['DOCUMENT_ROOT'].'/index.php')?'<input type="button" value="&nbsp;&nbsp;&nbsp;'.LoaderGetMessage("LOADER_BACK").'&nbsp;&nbsp;&nbsp;" onclick="document.location=\'/index.php?lang='.LANG.'\'">&nbsp;':'').
			'<input type="submit" value="&nbsp;&nbsp;&nbsp;'.LoaderGetMessage("LOADER_NEW_LOAD").'&nbsp;&nbsp;&nbsp;" id="download_button" '.($single ? '' : 'disabled').'>'
	);
}
elseif ($strAction=="LOAD")
{
	if (LANG == "ru")
	{
		$site = "https://www.1c-bitrix.ru/";
	}
	else
	{
		$site = "https://www.bitrixsoft.com/";
	}

	if (isset($_REQUEST['licence_type']) && $_REQUEST['licence_type'] == 'src' || isset($_REQUEST['LICENSE_KEY']) && $_REQUEST['LICENSE_KEY'])
	{
		$path = 'private/download/';
		$suffix = '_source.tar.gz';
		@mkdir($_SERVER['DOCUMENT_ROOT'].'/bitrix');
		$fres = @fopen($_SERVER['DOCUMENT_ROOT'].'/bitrix/license_key.php','wb');
		@fwrite($fres,'<'.'? $LICENSE_KEY = "'.EscapePHPString($_REQUEST['LICENSE_KEY']).'"; ?'.'>') && fclose($fres);
	}
	else
	{
		@unlink($_SERVER['DOCUMENT_ROOT'].'/bitrix/license_key.php');
		$path = 'download/';

		if ($edition == 2)
		{
			$suffix = '_encode_php5.tar.gz';
		}
		else
		{
			$suffix = '_encode.tar.gz';
		}
	}

	$ED = $arEditions[LANG][$edition];
	if (is_array($ED['LIST']))
	{
		$url = $_REQUEST['url'];
	}
	else
	{
		$url = $ED['LIST'];
	}

	if (isset($_REQUEST['licence_type']) && $_REQUEST['licence_type'] == 'src' || isset($_REQUEST['LICENSE_KEY']) && $_REQUEST['LICENSE_KEY'])
	{
		// different path for src
		if (($p = strpos($url, '/')) !== false)
		{
			$url = substr($url, $p + 1);
		}
	}

	$strRequestedUrl = $site.$path.$url.$suffix;

	$iTimeOut = TIMEOUT;

	$strUserAgent = "BitrixSiteLoader";
	$strFilename = $_SERVER["DOCUMENT_ROOT"]."/".basename($strRequestedUrl);

	$strLog = '';
	$status = '';
	if (isset($_REQUEST['start']) && $_REQUEST['start'])
	{
		$res = 2;
		SetCurrentProgress(1,100);
	}
	else
	{
		$res = LoadFile($strRequestedUrl.(($_REQUEST["LICENSE_KEY"] ?? '') <> '' ? "?lp=".md5($_REQUEST["LICENSE_KEY"]) : ''), $strFilename, $iTimeOut);
	}

	if (!$res)
	{
		$txt = nl2br($strLog);
	}
	elseif ($res==2) // частичная закачка
	{
		$txt = $status;
		$script = "<script>GoToPage(\"".$this_script_name."?action=LOAD&edition=".urlencode($edition)."&url=".urlencode($url)."&lang=".urlencode(LANG)."&LICENSE_KEY=".urlencode($_REQUEST["LICENSE_KEY"] ?? '')."&action_next=".urlencode($_REQUEST["action_next"] ?? '')."&xz=".rand(0, 32000)."\");</script>\n";
	}
	else
	{
		$txt = $status;
		$script = "<script>GoToPage(\"".$this_script_name."?action=UNPACK&by_step=Y&filename=".urlencode(basename($strRequestedUrl))."&lang=".urlencode(LANG)."&xz=".rand(0, 32000)."\");</script>\n";
	}

	$ar = array(
		'FORM' => $form,
		'TITLE' => LoaderGetMessage("LOADER_MENU_LOAD"),
		'HEAD' => LoaderGetMessage("LOADER_MENU_LOAD"),
		'TEXT' => $txt,
		'BOTTOM' => (file_exists($_SERVER['DOCUMENT_ROOT'].'/index.php') && $short ?'<input type="button" value="&nbsp;&nbsp;&nbsp;'.LoaderGetMessage("LOADER_BACK").'&nbsp;&nbsp;&nbsp;" onclick="document.location=\'/index.php?lang='.LANG.'\'">&nbsp;':'<input type="button" value="&nbsp;&nbsp;&nbsp;'.LoaderGetMessage("LOADER_BACK").'&nbsp;&nbsp;&nbsp;" onclick="document.location=\''.$this_script_name.'?action=LIST&lang='.LANG.'\'">')
	);
}
elseif ($strAction=="UNPACK")
{
	SetCurrentStatus(LoaderGetMessage("LOADER_UNPACK_ACTION"));
	$oArchiver = new CArchiver($_SERVER["DOCUMENT_ROOT"]."/".$_REQUEST["filename"], true);
	$tres = $oArchiver->extractFiles($_SERVER["DOCUMENT_ROOT"]);

	SetCurrentProgress($oArchiver->iCurPos, $oArchiver->iArchSize);

	/** @global $status */
	$txt = $status;

	if ($tres)
	{
		if (!$oArchiver->bFinish)
		{
			$script = "<script>GoToPage(\"".$this_script_name."?action=UNPACK&filename=".urlencode(basename($oArchiver->_strArchiveName))."&by_step=Y&lang=".urlencode(LANG)."&seek=".$oArchiver->iCurPos."\");</script>\n";
		}
		else // finish
		{
			$res = unlink($_SERVER["DOCUMENT_ROOT"]."/".$_REQUEST["filename"]) && unlink(__FILE__);
			@unlink(UPDATE_FLAG);
			@unlink($_SERVER["DOCUMENT_ROOT"]."/".$_REQUEST["filename"].'.log');
			@unlink($_SERVER["DOCUMENT_ROOT"]."/".$_REQUEST["filename"].'.tmp');

			@unlink($_SERVER['DOCUMENT_ROOT'].'/restore.php');
			$strInstFile = "index.php";

			if (!$res)
			{
				SetCurrentStatus(LoaderGetMessage("LOADER_UNPACK_DELETE"));
			}
			elseif (!file_exists($_SERVER["DOCUMENT_ROOT"]."/".$strInstFile))
			{
				SetCurrentStatus(LoaderGetMessage("LOADER_UNPACK_UNKNOWN"));
			}
			else
			{
				bx_accelerator_reset();
				SetCurrentStatus(LoaderGetMessage("LOADER_UNPACK_SUCCESS"));
				$script = "<script>document.location = \"/".$strInstFile."\";</script>";
			}
		}
	}
	else
	{
		SetCurrentStatus(LoaderGetMessage("LOADER_UNPACK_ERRORS"));
		$arErrors = $oArchiver->GetErrors();
		if (count($arErrors)>0)
		{
			if ($ft = fopen($_SERVER["DOCUMENT_ROOT"]."/".$this_script_name.".log", "wb"))
			{
				foreach ($arErrors as $value)
				{
					$str = "[".$value[0]."] ".$value[1]."\n";
					fwrite($ft, $str);
					$txt .= $str . '<br>';
				}
				fclose($ft);
			}
		}
	}

	$ar = array(
		'FORM' => $form,
		'TITLE' => LoaderGetMessage("LOADER_MENU_UNPACK"),
		'HEAD' => LoaderGetMessage("LOADER_MENU_UNPACK"),
		'TEXT' => $txt,
		'BOTTOM' => '<input type="button" value="&nbsp;&nbsp;&nbsp;'.LoaderGetMessage("LOADER_BACK").'&nbsp;&nbsp;&nbsp;" onclick="document.location=\''.$this_script_name.'?action=LIST\'">'
	);
}

########### HTML #########
html($ar);
echo $script;
##########################

function LoadFile($strRequestedUrl, $strFilename, $iTimeOut)
{
	global $proxyAddr, $proxyPort, $proxyUserName, $proxyPassword, $strUserAgent, $strRequestedSize;
	$ssl = preg_match('#https://#', $strRequestedUrl);

	$iTimeOut = intval($iTimeOut);
	if ($iTimeOut > 0)
	{
		$start_time = microtime(true);
	}

	$strRealUrl = $strRequestedUrl;
	$iStartSize = 0;

	$strRealUrl_tmp = "";
	$iRealSize_tmp = 0;
	if (file_exists($strFilename.".tmp") && file_exists($strFilename.".log") && filesize($strFilename.".log")>0)
	{
		$fh = fopen($strFilename.".log", "rb");
		$file_contents_tmp = fread($fh, filesize($strFilename.".log"));
		fclose($fh);

		list($strRealUrl_tmp, $iRealSize_tmp) = explode("\n", $file_contents_tmp);
		$strRealUrl_tmp = Trim($strRealUrl_tmp);
		$iRealSize_tmp = Trim($iRealSize_tmp);
	}
	if ($iRealSize_tmp<=0 || strlen($strRealUrl_tmp)<=0)
	{
		if (file_exists($strFilename.".tmp"))
		{
			@unlink($strFilename.".tmp");
		}

		if (file_exists($strFilename.".log"))
		{
			@unlink($strFilename.".log");
		}
	}
	else
	{
		$strRealUrl = $strRealUrl_tmp;
		$iStartSize = filesize($strFilename.".tmp");
	}

	do
	{
		$lasturl = $strRealUrl;

		$parsedurl = parse_url($strRealUrl);
		$useproxy = (($proxyAddr != "") && ($proxyPort != ""));

		if (!$useproxy)
		{
			$host = $parsedurl["host"];
			$port = $parsedurl["port"] ?? null;
			$hostname = $host;
		}
		else
		{
			$host = $proxyAddr;
			$port = $proxyPort;
			$hostname = $parsedurl["host"];
		}

		$port = $port ?: ($ssl ? 443 : 80);

		$sockethandle = fsockopen(($ssl ? 'ssl://' : '').$host, $port, $error_id, $error_msg, 30);
		if (!$sockethandle)
		{
			return false;
		}
		else
		{
			if (!$parsedurl["path"])
			{
				$parsedurl["path"] = "/";
			}

			$request = "";
			if (!$useproxy)
			{
				$request .= "HEAD ".$parsedurl["path"].(isset($parsedurl["query"]) ? '?'.$parsedurl["query"] : '')." HTTP/1.0\r\n";
				$request .= "Host: $hostname\r\n";
			}
			else
			{
				$request .= "HEAD ".$strRealUrl." HTTP/1.0\r\n";
				$request .= "Host: $hostname\r\n";
				if ($proxyUserName)
				{
					$request .= "Proxy-Authorization: Basic ".base64_encode($proxyUserName.":".$proxyPassword)."\r\n";
				}
			}

			if ($strUserAgent != "")
			{
				$request .= "User-Agent: $strUserAgent\r\n";
			}

			$request .= "\r\n";

			fwrite($sockethandle, $request);

			$replyheader = "";
			while (($result = fgets($sockethandle, 4024)) && $result!="\r\n")
			{
				$replyheader .= $result;
			}
			fclose($sockethandle);

			$ar_replyheader = explode("\r\n", $replyheader);

			$replycode = 0;
			$replymsg = "";
			if (preg_match("#([A-Z]{4})/([0-9.]{3}) ([0-9]{3})#", $ar_replyheader[0], $regs))
			{
				$replycode = intval($regs[3]);
				$replymsg = substr($ar_replyheader[0], strpos($ar_replyheader[0], $replycode) + strlen($replycode) + 1, strlen($ar_replyheader[0]) - strpos($ar_replyheader[0], $replycode) + 1);
			}

			if ($replycode!=200 && $replycode!=302)
			{
				if ($replycode==403)
				{
					SetCurrentStatus(LoaderGetMessage("LOADER_LOAD_SERVER_ANSWER1"));
				}
				else
				{
					SetCurrentStatus(str_replace("#ANS#", $replycode." - ".$replymsg, LoaderGetMessage("LOADER_LOAD_SERVER_ANSWER")).'<br>'.htmlspecialchars($strRequestedUrl));
				}
				return false;
			}

			$strLocationUrl = "";
			$iNewRealSize = 0;
			$strAcceptRanges = "";
			for ($i = 1; $i < count($ar_replyheader); $i++)
			{
				if (strpos($ar_replyheader[$i], "Location") !== false)
				{
					$strLocationUrl = trim(substr($ar_replyheader[$i], strpos($ar_replyheader[$i], ":") + 1, strlen($ar_replyheader[$i]) - strpos($ar_replyheader[$i], ":") + 1));
				}
				elseif (strpos($ar_replyheader[$i], "Content-Length") !== false)
				{
					$iNewRealSize = intval(Trim(substr($ar_replyheader[$i], strpos($ar_replyheader[$i], ":") + 1, strlen($ar_replyheader[$i]) - strpos($ar_replyheader[$i], ":") + 1)));
				}
				elseif (strpos($ar_replyheader[$i], "Accept-Ranges") !== false)
				{
					$strAcceptRanges = Trim(substr($ar_replyheader[$i], strpos($ar_replyheader[$i], ":") + 1, strlen($ar_replyheader[$i]) - strpos($ar_replyheader[$i], ":") + 1));
				}
			}

			if (strlen($strLocationUrl)>0)
			{
				$redirection = $strLocationUrl;
				if (!preg_match("#https?://#", $redirection))
				{
					$strRealUrl = dirname($lasturl)."/".$redirection;
				}
				else
				{
					$strRealUrl = $redirection;
				}
			}

			if (strlen($strLocationUrl)<=0)
			{
				break;
			}
		}
	}
	while (true);

	$bCanContinueDownload = ($strAcceptRanges == "bytes");

	if ($bCanContinueDownload)
	{
		$fh = fopen($strFilename.".log", "wb");
		if (!$fh)
		{
			SetCurrentStatus(str_replace("#FILE#", $strFilename.".log", LoaderGetMessage("LOADER_LOAD_NO_WRITE2FILE")));
			return false;
		}
		fwrite($fh, $strRealUrl."\n");
		fwrite($fh, $iNewRealSize."\n");
		fclose($fh);
	}

	$strRequestedSize = $iNewRealSize;

	$parsedurl = parse_url($strRealUrl);
	$useproxy = (($proxyAddr != "") && ($proxyPort != ""));

	if (!$useproxy)
	{
		$host = $parsedurl["host"];
		$port = $parsedurl["port"] ?? null;
		$hostname = $host;
	}
	else
	{
		$host = $proxyAddr;
		$port = $proxyPort;
		$hostname = $parsedurl["host"];
	}

	$port = $port ?: ($ssl ? 443 : 80);

	SetCurrentStatus(str_replace("#HOST#", $host, LoaderGetMessage("LOADER_LOAD_CONN2HOST")));
	$sockethandle = fsockopen(($ssl ? 'ssl://' : '').$host, $port, $error_id, $error_msg, 30);
	if (!$sockethandle)
	{
		SetCurrentStatus(str_replace("#HOST#", $host, LoaderGetMessage("LOADER_LOAD_NO_CONN2HOST"))." [".$error_id."] ".$error_msg);
		return false;
	}
	else
	{
		if (!$parsedurl["path"])
		{
			$parsedurl["path"] = "/";
		}

		SetCurrentStatus(LoaderGetMessage("LOADER_LOAD_QUERY_FILE"));

		$request = "";
		if (!$useproxy)
		{
			$request .= "GET ".$parsedurl["path"].(isset($parsedurl["query"]) ? '?'.$parsedurl["query"] : '')." HTTP/1.0\r\n";
			$request .= "Host: $hostname\r\n";
		}
		else
		{
			$request .= "GET ".$strRealUrl." HTTP/1.0\r\n";
			$request .= "Host: $hostname\r\n";
			if ($proxyUserName)
			{
				$request .= "Proxy-Authorization: Basic ".base64_encode($proxyUserName.":".$proxyPassword)."\r\n";
			}
		}

		if ($strUserAgent != "")
		{
			$request .= "User-Agent: $strUserAgent\r\n";
		}

		if ($bCanContinueDownload && $iStartSize > 0)
		{
			$request .= "Range: bytes=".$iStartSize."-\r\n";
		}

		$request .= "\r\n";

		fwrite($sockethandle, $request);

		SetCurrentStatus(LoaderGetMessage("LOADER_LOAD_WAIT"));

		$replyheader = "";
		while (($result = fgets($sockethandle, 4096)) && $result!="\r\n")
		{
			$replyheader .= $result;
		}

		$ar_replyheader = explode("\r\n", $replyheader);

		$replycode = 0;
		$replymsg = "";
		if (preg_match("#([A-Z]{4})/([0-9.]{3}) ([0-9]{3})#", $ar_replyheader[0], $regs))
		{
			$replycode = intval($regs[3]);
			$replymsg = substr($ar_replyheader[0], strpos($ar_replyheader[0], $replycode) + strlen($replycode) + 1, strlen($ar_replyheader[0]) - strpos($ar_replyheader[0], $replycode) + 1);
		}

		if ($replycode!=200 && $replycode!=302 && $replycode!=206)
		{
			SetCurrentStatus(str_replace("#ANS#", $replycode." - ".$replymsg, LoaderGetMessage("LOADER_LOAD_SERVER_ANSWER")));
			return false;
		}

		$strContentRange = "";
		$iContentLength = 0;
		for ($i = 1; $i < count($ar_replyheader); $i++)
		{
			if (strpos($ar_replyheader[$i], "Content-Range") !== false)
			{
				$strContentRange = trim(substr($ar_replyheader[$i], strpos($ar_replyheader[$i], ":") + 1, strlen($ar_replyheader[$i]) - strpos($ar_replyheader[$i], ":") + 1));
			}
			elseif (strpos($ar_replyheader[$i], "Content-Length") !== false)
			{
				$iContentLength = doubleval(Trim(substr($ar_replyheader[$i], strpos($ar_replyheader[$i], ":") + 1, strlen($ar_replyheader[$i]) - strpos($ar_replyheader[$i], ":") + 1)));
			}
		}
		
		$bReloadFile = true;
		if (strlen($strContentRange)>0)
		{
			if (preg_match("# *bytes +([0-9]*) *- *([0-9]*) */ *([0-9]*)#i", $strContentRange, $regs))
			{
				$iStartBytes_tmp = doubleval($regs[1]);
				$iEndBytes_tmp = doubleval($regs[2]);
				$iSizeBytes_tmp = doubleval($regs[3]);

				if ($iStartBytes_tmp==$iStartSize
					&& $iEndBytes_tmp==($iNewRealSize-1)
					&& $iSizeBytes_tmp==$iNewRealSize)
				{
					$bReloadFile = false;
				}
			}
		}

		if ($bReloadFile)
		{
			@unlink($strFilename.".tmp");
			$iStartSize = 0;
		}

		if (($iContentLength+$iStartSize)!=$iNewRealSize)
		{
			SetCurrentStatus(LoaderGetMessage("LOADER_LOAD_ERR_SIZE"));
			return false;
		}

		$fh = fopen($strFilename.".tmp", "ab");
		if (!$fh)
		{
			SetCurrentStatus(str_replace("#FILE#", $strFilename.".tmp", LoaderGetMessage("LOADER_LOAD_CANT_OPEN_WRITE")));
			return false;
		}

		$bFinished = true;
		$downloadsize = (double) $iStartSize;
		SetCurrentStatus(LoaderGetMessage("LOADER_LOAD_LOADING"));
		while (!feof($sockethandle))
		{
			if ($iTimeOut > 0 && (microtime(true) - $start_time) > $iTimeOut)
			{
				$bFinished = false;
				break;
			}

			$result = fread($sockethandle, 256 * 1024);
			$downloadsize += strlen($result);
			if ($result == "")
			{
				break;
			}

			fwrite($fh, $result);
		}
		SetCurrentProgress($downloadsize,$iNewRealSize);

		fclose($fh);
		fclose($sockethandle);

		if ($bFinished)
		{
			@unlink($strFilename);
			if (!@rename($strFilename.".tmp", $strFilename))
			{
				SetCurrentStatus(str_replace("#FILE2#", $strFilename, str_replace("#FILE1#", $strFilename.".tmp", LoaderGetMessage("LOADER_LOAD_ERR_RENAME"))));
				return false;
			}
			@unlink($strFilename.".tmp");
		}
		else
		{
			return 2;
		}

		SetCurrentStatus(str_replace("#SIZE#", $downloadsize, str_replace("#FILE#", $strFilename, LoaderGetMessage("LOADER_LOAD_FILE_SAVED"))));
		@unlink($strFilename.".log");
		return 1;
	}
}
function html($ar)
{
	$isCrm = getenv('BITRIX_ENV_TYPE') == 'crm';
	?>
	<html>
	<head>
		<title><?=$ar['TITLE']?></title>
	</head>
	<body>
	<script>
		function GoToPage(url)
		{
			window.setTimeout('document.location="' + url + '"', 500);
		}
	</script>
	<style>
		html, body {
			padding: 0 10px;
			margin: 0;
			background: #2fc6f7;
			position: relative;
		}
		p {
			margin: 0 0 40px;
			font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
			font-size:13px;
		}
		.wrap {
			min-height: 100vh;
			position: relative;
		}

		.cloud {
			background-size: contain;
			position: absolute;
			z-index: 1;
			background-repeat: no-repeat;
			background-position: center;
			opacity: .8;
		}

		.cloud-fill {
			background-image: url();
		}

		.cloud-border {
			background-image: url();
		}

		.cloud-1 {
			top: 9%;
			left: 50%;
			width: 60px;
			height: 38px;
		}

		.cloud-2 {
			top: 14%;
			left: 12%;
			width: 80px;
			height: 51px;
		}

		.cloud-3 {
			top: 11%;
			right: 14%;
			width: 106px;
			height: 67px;
		}

		.cloud-4 {
			top: 33%;
			right: 13%;
			width: 80px;
			height: 51px;
		}

		.cloud-5 {
			bottom: 23%;
			right: 12%;
			width: 80px;
			height: 51px;
		}

		.cloud-6 {
			bottom: 23%;
			left: 12%;
			width: 80px;
			height: 51px;
		}

		.cloud-7 {
			top: 13%;
			left: 6%;
			width: 60px;
			height: 31px;
			opacity: 1;
		}

		.cloud-8 {
			top: 43%;
			right: 6%;
			width: 86px;
			height: 54px;
			opacity: 1;
		}

		.header {
			min-height: 220px;
			max-width: 727px;
			margin: 0 auto;
			box-sizing: border-box;
			position: relative;
			z-index: 10;
		}

		.logo-link,
		.buslogo-link{
			position: absolute;
			top: 50%;
			margin-top: -23px;
		}

		.logo {
			width: 255px;
			display: block;
			height: 46px;
			background-repeat: no-repeat;
			/*background-size:cover;*/
		}

		.wrap.en .logo,
		.wrap.de .logo { background-image: url(); }

		.wrap.ru .logo { background-image: url(); }

		.wrap.ua .logo { background-image: url(); }

		.buslogo {
			width: 255px;
			display: block;
			height: 46px;
			background-repeat: no-repeat;
			/*background-size:cover;*/
		}

		.wrap.en .buslogo,
		.wrap.de .buslogo { background-image: url(); }

		.wrap.ru .buslogo { background-image: url(); }

		.wrap.ua .buslogo { background-image: url(); }

		.content {
			z-index: 10;
			position: relative;
			margin-bottom: 20px;
		}

		.content-container {
			z-index: 10;
			max-width: 727px;
			margin: 0 auto;
			padding: 28px 25px 25px;
			border-radius: 11px;
			box-shadow: 0 4px 20px 0 rgba(6, 54, 70, .15);
			box-sizing: border-box;
			text-align: center;
			background-color: #fff;
			position: relative;
		}

		.content-block {
			position: relative;
			z-index: 10;
		}

		hr {
			margin: 79px 0 45px;
			border: none;
			height: 1px;
			background: #f2f2f2;
		}

		h1.content-header {
			color: #2fc6f7;
			font: 500 40px/45px "Helvetica Neue", Helvetica, Arial, sans-serif;
			margin-bottom: 13px;
			margin-top: 62px;
		}

		h2.content-header {
			color: #2fc6f7;
			font: 400 27px/27px "Helvetica Neue", Helvetica, Arial, sans-serif;
			margin-bottom: 13px;
			margin-top: 31px;
		}

		h3.content-header {
			color: #000;
			font: 400 30px/41px "Helvetica Neue", Helvetica, Arial, sans-serif;
			margin-bottom: 40px;
			margin-top: 46px;
		}

		.content-logo {
			width: 100%;
			height: 57px;
			background-repeat: no-repeat;
			background-position: center 0;
		}

		.wrap.de .content-logo,
		.wrap.en .content-logo{ background-image: url(); }

		.wrap.ru .content-logo { background-image: url(); }

		.wrap.ua .content-logo { background-image: url(); }

		.setup-btn,
		.content-table input[type="submit"],
		.content-table input[type="button"]{
			height: 45px;
			line-height: 45px;
			color: #fff;
			background-color: #b5e00f;
			padding: 0 45px;
			text-transform: uppercase;
			text-decoration: none;
			font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
			vertical-align: middle;
			border-radius: 25px;
			transition: all 250ms ease;
			display: inline-block;
			font-size: 15px;
			border: none;
			cursor: pointer;
		}

		.setup-btn:hover {
			background-color: #9bc40e;
		}

		.lnk {
			color: #2fc6f7;
			font: 15px/25px "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
			border-bottom: 1px solid;
			text-decoration: none;
			transition: all 250ms ease;
		}

		.lnk:hover {
			border-bottom-color: transparent;
		}

		.progressbar-container {
			width: 70%;
			margin: 55px auto;
		}

		.progressbar-track {
			height: 19px;
			background: #edf2f5;
			border-radius: 9px;
			overflow: hidden;
			position: relative;
		}

		.progressbar-loader {
			position: absolute;
			left: 0;
			top: 0;
			bottom: 0;
			border-radius: 9px;
			background-image: url();
			background-position: 0 0;
			background-size: auto 19px;
			-webkit-animation: progressbar 2s infinite linear;
			-moz-animation: progressbar 2s infinite linear;
			-ms-animation: progressbar 2s infinite linear;
			-o-animation: progressbar 2s infinite linear;
			animation: progressbar 2s infinite linear;
		}

		@-webkit-keyframes progressbar { 0 {background-position: 0 0;} 100% {background-position: 75px 0;} }
		@-moz-keyframes progressbar { 0 {background-position: 0 0;} 100% {background-position: 75px 0;} }
		@-ms-keyframes progressbar { 0 {background-position: 0 0;} 100% {background-position: 75px 0;} }
		@-o-keyframes progressbar { 0 {background-position: 0 0;} 100% {background-position: 75px 0;} }
		@keyframes progressbar { 0 {background-position: 0 0;} 100% {background-position: 75px 0;} }

		.progressbar-counter {
			padding-top: 10px;
			color: #000;
			font: 300 28px/29px "Helvetica Neue", Helvetica, Arial, sans-serif;
			text-align: center;
		}

		.lang {
			vertical-align: middle;
			text-align: left;
			box-sizing: border-box;
			color: #333;
			font: 12px/22px "Helvetica Neue", Helvetica, Arial, sans-serif;
			display: block;
			text-decoration: none;
			padding: 5px 5px 5px 35px;
		}
		.lang:after {
			background: no-repeat center url();
			content: '';
			display: block;
			width:16px;
			height:12px;
			position: absolute;
			top: 50%;
			left: 12px;
			margin-top: -6px;
		}
		.lang.ru:after{ background-position: 0 0;}
		.lang.en:after{ background-position: 0 -13px;}
		.lang.ua:after{ background-position: 0 -26px;}
		.lang.de:after{ background-position: 0 -39px;}
		/**/
		.select-container{
			border:2px solid #d5dde0;
			height: 32px;
			position: absolute;
			right: 0;
			bottom: 0;
			width:50px;
			border-radius: 2px;
		}

		.select-container > .select-block,
		.selected-lang {
			width:100%;
			display: block;
			height: 32px;
			position: relative;
			cursor: pointer;
		}

		.selected-lang:before{
			content: '';
			border:4px solid #fff;
			border-top:4px solid #7e939b;
			display: block;
			position: absolute;
			right: 8px;
			top: 15px;
		}
		.selected-lang:after{
			left:11px;
		}

		.select-popup{
			display: none;
			position: absolute;
			top:100%;
			z-index:100;
			min-width:100%;
			border-radius:2px;
			padding:5px 0;
			background-color: #fff;
			box-shadow: 0 5px 5px rgba(0,0,0,.4);
		}
		.select-lang-item{
			height: 32px;
			width:100%;
			position: relative;
			padding:0 10px;
			box-sizing: border-box;
			transition: 220ms all ease;
		}
		.select-lang-item:hover{
			background-color: #f3f3f3;
		}
		.sub-header{
			font-size:21px;
			font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
			text-align: left;
			margin-bottom: 10px;
		}

		.select-version-container{
			padding: 10px 20px 20px;
			text-align: left;
			font-size:16px;
			line-height:25px;
			font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
		}

		.content-table {
			text-align: left;
			font-size:16px;
			font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
			width: 100%;
		}

		.input-license-container input,
		.content-table input[type="text"],
		.content-table select{
			width:100%;
			box-sizing: border-box;
			border: 2px solid #e0e6e9;
			border-radius:3px;
			font-size:15px;
			padding: 10px;
			outline: none !important;
		}
		.input-license-container{
			padding-bottom:40px;
		}
	</style>
	<div class="wrap <?=LANG?>">
		<header class="header">
			<?if ($isCrm || LANG != 'ru'):?>
				<a href="" target="_blank" class="logo-link"><span class="logo <?=LANG?>"></span></a>
			<?else:?>
				<a href="" target="_blank" class="buslogo-link"><span class="buslogo <?=LANG?>"></span></a>
			<?endif?>
		</header>
		<section class="content">
			<?=$ar['FORM']?>
			<div class="content-container">
				<table class="content-table">
					<tr>
						<td align=left style="/*font-size:14pt;color:#E11537;padding-left:25px*/">
							<h3 class="content-header" style="margin: 0;padding: 0;text-align: left;"><?=$ar['HEAD']?></h3>
							<hr style="margin: 15px 0;">
						</td>
					</tr>
					<tr>
						<td style="font-size:10pt" valign="<?=($ar['TEXT_ALIGN'] ?? 'middle')?>"><?=$ar['TEXT']?></td>
					</tr>
					<tr>
						<td style="font-size:10pt; padding-top: 20px" valign="middle" align="center" height="40px"><?=$ar['BOTTOM']?></td>
					</tr>
				</table>

				<div class="content-block">
					<div class="select-container" onclick="document.getElementById('lang-popup').style.display = document.getElementById('lang-popup').style.display == 'block' ? 'none' : 'block'">
						<label for="ss"><span class="selected-lang lang <?=LANG?>"></span></label>
						<div class="select-popup" id="lang-popup">
							<?
							$langs = array('en','de');
							if (LANG == 'ru')
							{
								$langs = array('en','de','ru');
							}
								
							foreach ($langs as $l)
							{
								?>
								<div class="select-lang-item">
									<a href="?lang=<?=$l?>" class="lang <?=$l?>"><?=$l?></a>
								</div>
								<?
							}
							?>
						</div>
					</div>
				</div>
			</div>
			</form>
		</section>
		<div class="cloud-layer">
			<div class="cloud cloud-1 cloud-fill"></div>
			<div class="cloud cloud-2 cloud-border"></div>
			<div class="cloud cloud-3 cloud-border"></div>
			<div class="cloud cloud-4 cloud-border"></div>
			<div class="cloud cloud-5 cloud-border"></div>
			<div class="cloud cloud-6 cloud-border"></div>
		</div>
	</div>
	</body>
	</html>
	<?
}

function SetCurrentStatus($str)
{
	global $strLog;
	$strLog .= $str."\n";
}

function SetCurrentProgress($cur, $total = 0)
{
	global $status;
	if (!$total)
	{
		$total=100;
		$cur=0;
	}
	$val = intval($cur/$total*100);
	if ($val > 99)
	{
		$val = 99;
	}

	$status = '
	<div class="progressbar-container">
		<div class="progressbar-track">
			<div class="progressbar-loader" style="width:'.$val.'%"></div>
		</div>
		<div class="progressbar-counter">'.$val.'%</div>
	</div>';
}

class CArchiver
{
	var $_strArchiveName = "";
	var $_bCompress = false;
	var $_strSeparator = " ";
	var $_dFile = 0;

	var $_arErrors = [];
	var $iArchSize = 0;
	var $iCurPos = 0;
	var $bFinish = false;

	function __construct($strArchiveName, $bCompress = false)
	{
		$this->_bCompress = false;
		if (!$bCompress)
		{
			if (file_exists($strArchiveName))
			{
				if ($fp = fopen($strArchiveName, "rb"))
				{
					$data = fread($fp, 2);
					fclose($fp);
					if ($data == "\37\213")
					{
						$this->_bCompress = true;
					}
				}
			}
			else
			{
				if (substr($strArchiveName, -2) == 'gz')
				{
					$this->_bCompress = true;
				}
			}
		}
		else
		{
			$this->_bCompress = true;
		}

		$this->_strArchiveName = $strArchiveName;
		$this->_arErrors = [];
	}

	function extractFiles($strPath, $vFileList = false)
	{
		$this->_arErrors = [];

		$v_list_detail = [];

		$strExtrType = "complete";
		$arFileList = 0;
		if ($vFileList!==false)
		{
			$arFileList = $this->_parseFileParams($vFileList);
			$strExtrType = "partial";
		}

		if ($v_result = $this->_openRead())
		{
			$v_result = $this->_extractList($strPath, $v_list_detail, $strExtrType, $arFileList, '');
			$this->_close();
		}

		return $v_result;
	}

	function GetErrors()
	{
		return $this->_arErrors;
	}

	function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path)
	{
		global $iNumDistrFiles;

		$v_result = true;
		$v_nb = 0;
		$v_extract_all = true;
		$v_listing = false;

		$p_path = str_replace("\\", "/", $p_path);

		if ($p_path == ''
			|| (substr($p_path, 0, 1) != '/'
				&& substr($p_path, 0, 3) != "../"
				&& !strpos($p_path, ':')))
		{
			$p_path = "./".$p_path;
		}

		$p_remove_path = str_replace("\\", "/", $p_remove_path);
		if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
		{
			$p_remove_path .= '/';
		}

		$p_remove_path_size = strlen($p_remove_path);

		switch ($p_mode)
		{
			case "complete" :
				$v_extract_all = true;
				$v_listing = FALSE;
				break;
			case "partial" :
				$v_extract_all = FALSE;
				$v_listing = FALSE;
				break;
			case "list" :
				$v_extract_all = FALSE;
				$v_listing = true;
				break;
			default :
				$this->_arErrors[] = array("ERR_PARAM", "Invalid extract mode (".$p_mode.")");
				return false;
		}

		clearstatcache();

		$tm=time();
		while((extension_loaded("mbstring")? mb_strlen($v_binary_data = $this->_readBlock(), "latin1") : strlen($v_binary_data = $this->_readBlock())) != 0)
		{
			$v_extract_file = FALSE;
			$v_extraction_stopped = 0;

			if (!$this->_readHeader($v_binary_data, $v_header))
			{
				return false;
			}

			if ($v_header['filename'] == '')
			{
				continue;
			}

			// ----- Look for long filename
			if ($v_header['typeflag'] == 'L')
			{
				if (!$this->_readLongHeader($v_header))
				{
					return false;
				}
			}


			if ((!$v_extract_all) && (is_array($p_file_list)))
			{
				// ----- By default no unzip if the file is not found
				$v_extract_file = false;

				for ($i = 0; $i < count($p_file_list); $i++)
				{
					// ----- Look if it is a directory
					if (substr($p_file_list[$i], -1) == '/')
					{
						// ----- Look if the directory is in the filename path
						if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
							&& (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]))
						{
							$v_extract_file = true;
							break;
						}
					}
					elseif ($p_file_list[$i] == $v_header['filename'])
					{
						// ----- It is a file, so compare the file names
						$v_extract_file = true;
						break;
					}
				}
			}
			else
			{
				$v_extract_file = true;
			}

			// ----- Look if this file need to be extracted
			if ($v_extract_file && !$v_listing)
			{
				if (($p_remove_path != '')
					&& (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path))
				{
					$v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
				}
				if (($p_path != './') && ($p_path != '/'))
				{
					while (substr($p_path, -1) == '/')
					{
						$p_path = substr($p_path, 0, strlen($p_path)-1);
					}

					if (substr($v_header['filename'], 0, 1) == '/')
					{
						$v_header['filename'] = $p_path.$v_header['filename'];
					}
					else
					{
						$v_header['filename'] = $p_path.'/'.$v_header['filename'];
					}
				}
				if (file_exists($v_header['filename']))
				{
					if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == ''))
					{
						$this->_arErrors[] = array("DIR_EXISTS", "File '".$v_header['filename']."' already exists as a directory");
						return false;
					}
					if ((is_file($v_header['filename'])) && ($v_header['typeflag'] == "5"))
					{
						$this->_arErrors[] = array("FILE_EXISTS", "Directory '".$v_header['filename']."' already exists as a file");
						return false;
					}
					if (!is_writeable($v_header['filename']))
					{
						$this->_arErrors[] = array("FILE_PERMS", "File '".$v_header['filename']."' already exists and is write protected");
						return false;
					}
				}
				elseif (($v_result = $this->_dirCheck(($v_header['typeflag'] == "5" ? $v_header['filename'] : dirname($v_header['filename'])))) != 1)
				{
					$this->_arErrors[] = array("NO_DIR", "Unable to create path for '".$v_header['filename']."'");
					return false;
				}

				if ($v_extract_file)
				{
					if ($v_header['typeflag'] == "5")
					{
						if (!@file_exists($v_header['filename']))
						{
							if (!@mkdir($v_header['filename'], BX_DIR_PERMISSIONS))
							{
								$this->_arErrors[] = array("ERR_CREATE_DIR", "Unable to create directory '".$v_header['filename']."'");
								return false;
							}
						}
					}
					else
					{
						if (($v_dest_file = fopen($v_header['filename'], "wb")) == 0)
						{
							$this->_arErrors[] = array("ERR_CREATE_FILE", LoaderGetMessage('NO_PERMS') .' '. $v_header['filename']);
							return false;
						}
						else
						{
							$n = floor($v_header['size']/512);
							for ($i = 0; $i < $n; $i++)
							{
								$v_content = $this->_readBlock();
								fwrite($v_dest_file, $v_content, 512);
							}
							if (($v_header['size'] % 512) != 0)
							{
								$v_content = $this->_readBlock();
								fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
							}

							@fclose($v_dest_file);

							@chmod($v_header['filename'], BX_FILE_PERMISSIONS);
							@touch($v_header['filename'], $v_header['mtime']);
						}

						clearstatcache();
						if (filesize($v_header['filename']) != $v_header['size'])
						{
							$this->_arErrors[] = array("ERR_SIZE_CHECK", "Extracted file '".$v_header['filename']."' have incorrect file size '".filesize($v_header['filename'])."' (".$v_header['size']." expected). Archive may be corrupted");
							return false;
						}
					}
				}
				else
				{
					$this->_jumpBlock(ceil(($v_header['size']/512)));
				}
			}
			else
			{
				$this->_jumpBlock(ceil(($v_header['size']/512)));
			}

			if ($v_listing || $v_extract_file || $v_extraction_stopped)
			{
				if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'])
				{
					$v_file_dir = '';
				}
				if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
				{
					$v_file_dir = '/';
				}

				$p_list_detail[$v_nb++] = $v_header;

				if ($v_nb % 100 == 0)
				{
					SetCurrentProgress($this->iCurPos, $this->iArchSize);
				}
			}

			if ($_REQUEST['by_step'] && (time()-$tm) > TIMEOUT)
			{
				SetCurrentProgress($this->iCurPos, $this->iArchSize);
				return true;
			}
		}
		$this->bFinish = true;
		return true;
	}

	function _readBlock()
	{
		$v_block = "";
		if (is_resource($this->_dFile))
		{
			if (isset($_REQUEST['seek']))
			{
				if ($this->_bCompress)
				{
					gzseek($this->_dFile, intval($_REQUEST['seek']));
				}
				else
				{
					fseek($this->_dFile, intval($_REQUEST['seek']));
				}

				$this->iCurPos = intval($_REQUEST['seek']);

				unset($_REQUEST['seek']);
			}
			if ($this->_bCompress)
			{
				$v_block = gzread($this->_dFile, 512);
			}
			else
			{
				$v_block = fread($this->_dFile, 512);
			}

			$this->iCurPos +=  (extension_loaded("mbstring")? mb_strlen($v_block, "latin1") : strlen($v_block));
		}
		return $v_block;
	}

	function _readHeader($v_binary_data, &$v_header)
	{
		if ((extension_loaded("mbstring")? mb_strlen($v_binary_data, "latin1") : strlen($v_binary_data)) ==0)
		{
			$v_header['filename'] = '';
			return true;
		}

		if ((extension_loaded("mbstring")? mb_strlen($v_binary_data, "latin1") : strlen($v_binary_data)) != 512)
		{
			$v_header['filename'] = '';
			$this->_arErrors[] = array("INV_BLOCK_SIZE", "Invalid block size : ".strlen($v_binary_data)."");
			return false;
		}

		$chars = count_chars(substr($v_binary_data,0,148).'        '.substr($v_binary_data,156,356));
		$v_checksum = 0;
		foreach($chars as $ch => $cnt)
			$v_checksum += $ch*$cnt;

		$v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12temp", $v_binary_data);

		$v_header['checksum'] = octdec(trim($v_data['checksum']));
		if ($v_header['checksum'] != $v_checksum)
		{
			$v_header['filename'] = '';

			if (($v_checksum == 256) && ($v_header['checksum'] == 0))
			{
				return true;
			}

			$this->_arErrors[] = array("INV_BLOCK_CHECK", "Invalid checksum for file '".$v_data['filename']."' : ".$v_checksum." calculated, ".$v_header['checksum']." expected");
			return false;
		}

		// ----- Extract the properties
		$v_header['filename'] = trim($v_data['prefix'], "\x00")."/".trim($v_data['filename'], "\x00");
		$v_header['mode'] = octdec(trim($v_data['mode']));
		$v_header['uid'] = octdec(trim($v_data['uid']));
		$v_header['gid'] = octdec(trim($v_data['gid']));
		$v_header['size'] = octdec(trim($v_data['size']));
		$v_header['mtime'] = octdec(trim($v_data['mtime']));
		if (($v_header['typeflag'] = $v_data['typeflag']) == "5")
		{
			$v_header['size'] = 0;
		}

		return true;
	}

	function _readLongHeader(&$v_header)
	{
		$v_filename = '';
		$n = floor($v_header['size']/512);
		for ($i = 0; $i < $n; $i++)
		{
			$v_content = $this->_readBlock();
			$v_filename .= $v_content;
		}
		if (($v_header['size'] % 512) != 0)
		{
			$v_content = $this->_readBlock();
			$v_filename .= $v_content;
		}

		$v_binary_data = $this->_readBlock();

		if (!$this->_readHeader($v_binary_data, $v_header))
		{
			return false;
		}

		$v_header['filename'] = trim($v_filename, "\x00");

		return true;
	}

	function _jumpBlock($p_len = false)
	{
		if (is_resource($this->_dFile))
		{
			if ($p_len === false)
			{
				$p_len = 1;
			}

			if ($this->_bCompress)
			{
				gzseek($this->_dFile, gztell($this->_dFile)+($p_len*512));
			}
			else
			{
				fseek($this->_dFile, ftell($this->_dFile)+($p_len*512));
			}
		}
		return true;
	}

	function _parseFileParams(&$vFileList)
	{
		if (isset($vFileList) && is_array($vFileList))
		{
			return $vFileList;
		}
		elseif (isset($vFileList) && strlen($vFileList)>0)
		{
			return explode($this->_strSeparator, $vFileList);
		}
		return [];
	}

	function _openRead()
	{

		if ($this->_bCompress)
		{
			$this->_dFile = gzopen($this->_strArchiveName, "rb");
			$this->iArchSize = filesize($this->_strArchiveName) * 3;
		}
		else
		{
			$this->_dFile = fopen($this->_strArchiveName, "rb");
			$this->iArchSize = filesize($this->_strArchiveName);
		}

		if (!$this->_dFile)
		{
			$this->_arErrors[] = array("ERR_OPEN", "Unable to open '".$this->_strArchiveName."' in read mode");
			return false;
		}

		return true;
	}

	function _close()
	{
		if (is_resource($this->_dFile))
		{
			if ($this->_bCompress)
			{
				gzclose($this->_dFile);
			}
			else
			{
				fclose($this->_dFile);
			}

			$this->_dFile = 0;
		}

		return true;
	}

	function _dirCheck($p_dir)
	{
		if ((is_dir($p_dir)) || ($p_dir == ''))
		{
			return true;
		}

		$p_parent_dir = dirname($p_dir);

		if (($p_parent_dir != $p_dir) &&
			($p_parent_dir != '') &&
			(!$this->_dirCheck($p_parent_dir)))
		{
			return false;
		}

		if (!is_dir($p_dir) && !mkdir($p_dir, BX_DIR_PERMISSIONS))
		{
			$this->_arErrors[] = array("CANT_CREATE_PATH", "Unable to create directory '".$p_dir."'");
			return false;
		}

		return true;
	}

}

function img($name)
{
	if (file_exists($_SERVER['DOCUMENT_ROOT'].'/images/'.$name))
	{
		return '/images/'.$name;
	}
	if (LANG == 'ru')
	{
		return 'https://www.1c-bitrix.ru/images/bitrix_setup/'.$name;
	}
	return 'https://www.bitrixsoft.com/images/bitrix_setup/'.$name;

}

function ShowError($str)
{
	return	'<div style="color:red;text-align:center;border:1px solid red;padding:5px;">'.$str.'</div>';
}

function bx_accelerator_reset()
{
	if (function_exists("accelerator_reset"))
	{
		accelerator_reset();
	}
}

function EscapePHPString($str)
{
	$str = str_replace("\\", "\\\\", $str);
	$str = str_replace("\$", "\\\$", $str);
	$str = str_replace("\"", "\\"."\"", $str);
	return $str;
}
